#include<stdio.h>
#include "include/Arcroll.h"
#define Matrix4x4 Viewer_Matrix4x4_
#include<Mesh_IO/Mesh_IO.h>
#include<tool/libcell_tools_view.h>
#include <tool/libcell_tools_formats.h>
#include<zkhy_tools/zkhy_find_wall.h>
#include<points_cloud_algorithm.h>
#include<tool/libcell_tools_algorithm.h>
#include <Dense>
#include<SVD>
#include<iostream>
using namespace Eigen;

#define quote lib_cell_quote
#define _ReadOff_   LibCell_ReadOff_
#define _ReadCell_  LibCell_ReadCell_
#define _WriteCell_ LibCell_WriteCell_
#define _ReadArray_ LibCell_ReadArray_
typedef struct Points_Cluster{
    Node* value;
    float n[3];
    float c[3];
    void* prop;

}Points_Cluster;

typedef struct Temp_intera{

    Node*value;
    Viewer_Something* vs; 
    Viewer_Opengl_Interpreter* voi;
    void*prop; 
}Temp_intera;
void temp_intera_key_callback(Viewer_Intera*vi)
{
    Temp_intera* ti=(Temp_intera*)(vi->representation);
    Interactor_GlobalInfo* g_info=vi->g_info; 

    if(g_info->key_action==VIEWER_PRESS&&g_info->key==VIEWER_KEY_U)
    {
        if(ti->value!=NULL)
        {
            ti->value=(Node*)(ti->value->Next); 
        }
        else
        {
            return;
        }
        Points_Cluster* pc=(Points_Cluster*)(ti->value->value);
        printf("n:%lf %lf %lf c:%lf %lf %lf \n",pc->n[0],pc->n[1],pc->n[2],pc->c[0],pc->c[1],pc->c[2] );

        Viewer_Something* vs=(Viewer_Something*)(ti->vs);   
        auto vp=(Viewer_Points*)(vs->evolution);

        vp->Data_rows=node_size(pc->value);
        vp->pointsize=5.0;
        if(vp->Data!=NULL)
        {
            free(vp->Data);
            vp->Data=NULL;  
        }
        vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
        float color[4]={0}; 
        color[0]=0.8;color[1]=0.4;color[2]=0.5;color[3]=1;
        int i=0;
        for(Node* nit=pc->value;nit!=NULL;nit=(Node*)(nit->Next))
        {
            vp->Data[i*3+0]=((template_v*)(nit->value))->point[0];
            vp->Data[i*3+1]=((template_v*)(nit->value))->point[1];
            vp->Data[i*3+2]=((template_v*)(nit->value))->point[2];
            i++;
        } 
        //free(vp->color);

       // vp->color=NULL;
        //
       vp->set_color(vp,color);
       // ti->voi->update=1;
        //printf("%d\n",i );
        ti->voi->update_data(ti->voi);

    }
}


void set_default_voi(Viewer_Opengl_Interpreter* voi,Viewer_World*vw)
{

    //Viewer_World_Manager* vwm=(Viewer_World_Manager*)malloc(sizeof(Viewer_World_Manager));
     
    char camera[]="Camera";
    Node* n=vw->create_something(vw,camera);
    Viewer_Something*ms=(Viewer_Something*)(n->value);
    Viewer_Camera*mc=(Viewer_Camera*)(ms->evolution);
    mc->is_using=1;
    Matrix4x4 *p=Projection(M_PI/3.0f,(float)(vw->g_info->resolution[0])/(float)(vw->g_info->resolution[1]),0.5f,200.0f);
    p->copy_data(mc->Proj,p);
    Matrix4x4_free(p);

    free_node(n);

    char edges[]="Edges";
//**********************************

    n=vw->create_something(vw,edges);
    auto vs=(Viewer_Something*)(n->value);
  //  vs->disappear=1;
    auto ve=(Viewer_Edges*)(vs->evolution);
    ve->Data_rows=4;
    ve->Data_index_rows=3;
    ve->Data=(float*)malloc(sizeof(float)*3*ve->Data_rows);
    ve->Data_index=(unsigned int*)malloc(sizeof(unsigned int)*2*ve->Data_index_rows);     
    ve->Data[0]=0;ve->Data[1]=0;ve->Data[2]=0;
    ve->Data[3]=1;ve->Data[4]=0;ve->Data[5]=0;
    ve->Data[6]=0;ve->Data[7]=1;ve->Data[8]=0; 
    ve->Data[9]=0;ve->Data[10]=0;ve->Data[11]=1;
   

    ve->Data_index[0]=0;ve->Data_index[1]=1;
    ve->Data_index[2]=0;ve->Data_index[3]=2; 
    ve->Data_index[4]=0;ve->Data_index[5]=3;


    ve->color_rows=ve->Data_index_rows;
    ve->color=(float*)malloc(sizeof(float)*4*ve->color_rows);
    memset(ve->color,0,sizeof(float)*4*ve->color_rows);

    ve->color[0]=1;ve->color[1]=0; ve->color[2]=0;ve->color[3]=1;
    ve->color[4]=0;ve->color[5]=1; ve->color[6]=0;ve->color[7]=1;
    ve->color[8]=0;ve->color[9]=0; ve->color[10]=1;ve->color[11]=1;
    free_node(n); 
//********//
    Viewer_Arcroll*ma=(Viewer_Arcroll*)malloc(sizeof(Viewer_Arcroll));
    Viewer_Arcroll_init(ma);
    ma->mc=mc;
    ma->vw=vw;
    ma->voi=voi;
    
    ma->vs=vs;
//****//
    char intera[]="Intera";
    n=vw->create_something(vw,intera);
    ms=(Viewer_Something*)(n->value);

    Viewer_Intera* mi=(Viewer_Intera*)(ms->evolution);
    mi->representation=(void*)ma;
    mi->cursor_position_callback=viewer_Arcroll_cursor_position_callback;
    mi->scroll_callback=viewer_Arcroll_scroll_callback;
    mi->mouse_button_callback=viewer_Arcroll_mouse_button_callback;
    mi->drop_callback=viewer_Arcroll_drop_callback;
    mi->key_callback=viewer_Arcroll_key_callback;
    free_node(n);

}


static bool points_cloud_vertex_is_in_triangle(double *p,double * p1,double * p2,double *p3,double * n)
{

    Matrix4x4* mat=(Matrix4x4*)malloc(sizeof(Matrix4x4));
    Matrix4x4_init_float(mat);

    float* data=(float*)(mat->data);
    data[0*4+0]=p2[0]-p1[0]; data[1*4+0]=p2[1]-p1[1];data[2*4+0]=p2[2]-p1[2];
    data[0*4+1]=p3[0]-p1[0]; data[1*4+1]=p3[1]-p1[1];data[2*4+1]=p3[2]-p1[2];
    data[0*4+2]=n[0]; data[1*4+2]=n[1];data[2*4+2]=n[2];
    double y[3]={p[0]-p1[0],p[1]-p1[1],p[2]-p1[2]};

    Matrix4x4* mati=mat->inverse(mat);
    double x[3]={0,0,0};
    if(mati==NULL)
    {
        printf("mati is null\n");
        Matrix4x4_free(mat);
        return false;
    } 
    else
    {
        data=(float*)(mati->data);
        for(int i=0;i<3;i++)
        {
            for(int j=0;j<3;j++)
            {
                x[i]+=data[i*4+j]*y[j];
            }
        }
        Matrix4x4_free(mati); 
    }
    Matrix4x4_free(mat);
    printf("x:%lf %lf %lf\n",x[0],x[1],x[2] );
    if(x[0]<0||x[1<0]||x[0]>1||x[1]>1)
    {
        return false;
    }

    return true;
}
void test_vertex_is_in_triangle()
{
    double p[3]={2.3,3.1,4.923},p1[3]={-2.324,322.1,-23.91},p2[3]={-231.34,-231.99,303},p3[3]={321.91,12.49,-23.9};
    double n[3]={1.139,-0.21,0.13};
    if(points_cloud_vertex_is_in_triangle(p,p1,p2,p3,n))
    {
        printf("is in triangle\n");
    }
    else
    {
        printf("not in triangle\n");
    }
}

void test_construct_mesh(Viewer_World* vw)
{

    Mesh mesh;
    Mesh_init(&mesh);
    _Read_(&mesh,"0727.obj");
    ////***********************
    char points[]="Points";
    Node* n=vw->create_something(vw,points);
    auto vs=(Viewer_Something*)(n->value);
    auto vp=(Viewer_Points*)(vs->evolution);
    
    Node* node=NULL;
    
    vp->Data_rows=mesh.num_v(&mesh);
    vp->pointsize=6.0;
    vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
    int i=0;
    for(auto vit=mesh.v_begin(&mesh);vit!=mesh.v_end(&mesh);vit++)
    {
        vp->Data[i*3+0]=((template_v*)(quote(vit)))->point[0];
        vp->Data[i*3+1]=((template_v*)(quote(vit)))->point[1];
        vp->Data[i*3+2]=((template_v*)(quote(vit)))->point[2];
        i++;
    } 
    float color[4]={0.9,0.3,0.8,1.0};

    vp->set_color(vp,color); 
    free_node(node_reverse(n));
    ////******************************
    n=vw->create_something(vw,points);
    vs=(Viewer_Something*)(n->value); 
    vp=(Viewer_Points*)(vs->evolution);
    vp->Data_rows=2;
    vp->pointsize=10.0;
    vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
    template_v v1=mesh.get_vertex(&mesh,353);
    vp->Data[0]=v1.point[0];vp->Data[1]=v1.point[1];vp->Data[2]=v1.point[2];
    v1=mesh.get_vertex(&mesh,179);
    vp->Data[3]=v1.point[0];vp->Data[4]=v1.point[1];vp->Data[5]=v1.point[2];
    color[0]=0;color[1]=0.8;
    vp->set_color(vp,color);
    free_node(node_reverse(n));
    /////**********************///////////
   
     
    KD_Node*kn=create_kd_tree_from_mesh(&mesh);
    template_v*v=quote(mesh.v_begin(&mesh));
    template_v*vs1[3]={v,NULL,NULL};
    KD_Node* kn1=kd_tree_find_nearest_and_except_vs(v,kn,vs1,1);
    vs1[1]=kn1->value;
    kn1=kd_tree_find_nearest_and_except_vs(v,kn,vs1,2);
    vs1[2]=kn1->value;
    printf("%d %d %d\n",vs1[0]->id,vs1[1]->id,vs1[2]->id);
    template_c* c=mesh.create_cellv(&mesh,vs1,3);
    mesh.external_cell_init_(&mesh);
    points_cloud_construct_mesh_from_mesh(&mesh,kn,500);    

    free_kdnode(kn);
    ////*************************///////
    char faces[]="Faces";
    n=vw->create_something(vw,faces);
    vs=(Viewer_Something*)(n->value);
    auto vf=(Viewer_Faces*)(vs->evolution);
    vf->Data_rows=mesh.num_v(&mesh);
    vf->Data_index_rows=mesh.num_c(&mesh);
    get_data_from_2dim_cell(&mesh,&(vf->Data),&(vf->Data_index));
    vf->normal_rows=mesh.num_c(&mesh);
    vf->color_rows=mesh.num_c(&mesh);

    vf->set_color(vf,color);
    vf->compute_normal(vf);
    vf->is_reversal_normal=1;
   // free_kdnode(kn1);
    
}

void test_divide_oc(Mesh * m,OC_Node* ocn)
{
    template_v* v=quote(m->v_begin(m));
    double xs[2]={0},ys[2]={0},zs[2]={0},centroid[3]={0};
    xs[0]=v->point[0];xs[1]=v->point[0];
    ys[0]=v->point[1];ys[1]=v->point[1];
    zs[0]=v->point[2];zs[1]=v->point[2];
    int sum=0;
    for(auto vit=m->v_begin(m);vit!=m->v_end(m);vit++)
    {
        v=quote(vit);
        centroid[0]+=v->point[0];centroid[1]+=v->point[1];centroid[2]+=v->point[2];
        if(v->point[0]<xs[0])
        {
            xs[0]=v->point[0];
        }
        else if(v->point[0]>xs[1])
        {
            xs[1]=v->point[0];
        }

        if(v->point[1]<ys[0])
        {
            ys[0]=v->point[1];
        }
        else if(v->point[1]>ys[1])
        {
            ys[1]=v->point[1];
        }
        if(v->point[2]<zs[0])
        {
            zs[0]=v->point[2];
        }
        else if(v->point[2]>zs[1])
        {
            zs[1]=v->point[2];
        }
        sum++;
    } 
    centroid[0]/=(double)sum; centroid[1]/=(double)sum; centroid[2]/=(double)sum; 

   // printf("%lf  %lf %lf \n",centroid[0],centroid[1],centroid[2] );
    ocn->loc_min[0]=xs[0];ocn->loc_min[1]=ys[0];ocn->loc_min[2]=zs[0];
    double max=xs[1]-xs[0];
    if(ys[1]-ys[0]>max)
    {
        max=ys[1]-ys[0];
    }
    if(zs[1]-zs[0]>max)
    {
        max=zs[1]-zs[0];
    }

    ocn->loc_max[0]=max+ocn->loc_min[0];ocn->loc_max[1]=max+ocn->loc_min[1];ocn->loc_max[2]=max+ocn->loc_min[2];

    for(auto vit=m->v_begin(m);vit!=m->v_end(m);vit++)
    {
        ocn->value=node_overlying(ocn->value,quote(vit));
    } 
    int num1=0,num2=m->num_v(m)/200;
    do{
        num1=oc_node_divide_all_leaves(ocn);

    }while(num1<num2);
/*    printf("num1: %d %d\n", num1,num2); ****/

}


int cmp_node(void *a,void * b)
{
    Node* a1=((Points_Cluster*)(a))->value,* b1=((Points_Cluster*)(b))->value;
    int i=node_size(a1),j=node_size(b1);
    if(i==j)
    {
        return 0;
    }
    else if(i>j)
    {
        return 1;
    }
    else
    {
        return -1;
    }
}
void test_division_earth(Viewer_World * vw,Viewer_Opengl_Interpreter* voi)
{
    Mesh mesh;
    Mesh_init(&mesh);
    _Read_(&mesh,"tree1.off");

    Mesh_adjust_mesh_to_unit_hexahedron(&mesh);
    char points[]="Points";
    Node* n=vw->create_something(vw,points);
    auto vs=(Viewer_Something*)(n->value);
    auto vp=(Viewer_Points*)(vs->evolution);
    
    Node* node=NULL;
    
    vp->Data_rows=mesh.num_v(&mesh);
    vp->pointsize=4.0;
    vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
    int i=0;
    for(auto vit=mesh.v_begin(&mesh);vit!=mesh.v_end(&mesh);vit++)
    {
        vp->Data[i*3+0]=((template_v*)(quote(vit)))->point[0];
        vp->Data[i*3+1]=((template_v*)(quote(vit)))->point[1];
        vp->Data[i*3+2]=((template_v*)(quote(vit)))->point[2];
        i++;
    } 
    float color[4]={0.4,0.6,0.8,1.0};

    vp->set_color(vp,color); 
    free_node(node_reverse(n));
    

    OC_Node * ocn=(OC_Node*)malloc(sizeof(OC_Node));
    OC_Node_init(ocn);
    test_divide_oc(&mesh,ocn);

    //************************************
    // Octree_Trav otr=octree_begin(ocn);
    // for(;otr!=octree_end(ocn);otr++)
    // {
    //     i=node_size(otr.it->value);
    //     if(i>50)
    //     {
    //         Points_Cluster* pcn=(Points_Cluster*)malloc(sizeof(Points_Cluster));
    //         pcn->value=node_copy(otr.it->value);
    //         MatrixXf A;
    //         A.resize(i,3);
    //         A.setZero();
    //         template_v* v=NULL;
    //         double centroid[3]={0};
    //         for(Node* nit=otr.it->value;nit!=NULL;nit=(Node*)(nit->Next))
    //         {
    //             v=(template_v*)(nit->value);
    //             centroid[0]+=v->point[0];centroid[1]+=v->point[1];centroid[2]+=v->point[2]; 
    //         }
    //         centroid[0]/=(double)i;centroid[1]/=(double)i;centroid[2]/=(double)i;
    //         i=0;
    //         for(Node* nit=otr.it->value;nit!=NULL;nit=(Node*)(nit->Next))
    //         {
    //             v=(template_v*)(nit->value);
    //             A(i,0)=v->point[0]-centroid[0];A(i,1)=v->point[1]-centroid[1];A(i,2)=v->point[2]-centroid[2];
    //             i++;
    //         }
    //         JacobiSVD<Eigen::MatrixXf> svd(A,ComputeThinU | ComputeThinV);
    //         MatrixXf V=svd.matrixV();
    //         std::cout<<"V:"<<std::endl<<V<<std::endl;
    //         break;
    //     } 
    // }
    // n=vw->create_something(vw,points);
    // vs=(Viewer_Something*)(n->value);
    // vp=(Viewer_Points*)(vs->evolution);

    // vp->Data_rows=node_size(otr.it->value);

    // vp->pointsize=5.0;
    // vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
    // color[0]=0.8;color[1]=0.4;color[2]=0.5;
    // i=0;
    // for(Node* nit=otr.it->value;nit!=NULL;nit=(Node*)(nit->Next))
    // {
    //     vp->Data[i*3+0]=((template_v*)(nit->value))->point[0];
    //     vp->Data[i*3+1]=((template_v*)(nit->value))->point[1];
    //     vp->Data[i*3+2]=((template_v*)(nit->value))->point[2];
    //     i++;
    // } 
    // printf("i:%d\n",vp->Data_rows );
    // vp->set_color(vp,color);
    // free_node(node_reverse(n));

    //************************************

    Node* node_cube_kinds=NULL;
    Octree_Trav otr=octree_begin(ocn);
    int jj=0;
    for(;otr!=octree_end(ocn);otr++)
    {
        i=node_size(otr.it->value);

        if(i>50)
        {
            //printf("i:%d\n",i );
            Points_Cluster* pcn=(Points_Cluster*)malloc(sizeof(Points_Cluster));
            pcn->value=node_copy(otr.it->value);
            MatrixXf A;
            A.resize(i,3);
            A.setZero();
            template_v* v=NULL;
            double centroid[3]={0};
            for(Node* nit=otr.it->value;nit!=NULL;nit=(Node*)(nit->Next))
            {
                v=(template_v*)(nit->value);
                centroid[0]+=v->point[0];centroid[1]+=v->point[1];centroid[2]+=v->point[2]; 
            }
            centroid[0]/=(double)i;centroid[1]/=(double)i;centroid[2]/=(double)i;
            i=0;
            for(Node* nit=otr.it->value;nit!=NULL;nit=(Node*)(nit->Next))
            {
                v=(template_v*)(nit->value);
                A(i,0)=v->point[0]-centroid[0];A(i,1)=v->point[1]-centroid[1];A(i,2)=v->point[2]-centroid[2];
                i++;
            }


            JacobiSVD<Eigen::MatrixXf> svd(A,ComputeThinU | ComputeThinV);

            MatrixXf V=svd.matrixV();
            pcn->n[0]=V(0,2);pcn->n[1]=V(1,2);pcn->n[2]=V(2,2);
            pcn->c[0]=centroid[0];pcn->c[1]=centroid[1];pcn->c[2]=centroid[2];
           // printf("n:%lf %lf %lf centroid:%lf %lf %lf\n",pcn->n[0],pcn->n[1],pcn->n[2],pcn->c[0],pcn->c[1],pcn->c[2]);  
            int flag=0;
            for(Node* nit=node_reverse(node_cube_kinds);nit!=NULL;nit=(Node*)(nit->Prev))
            {
                Points_Cluster* pc=(Points_Cluster*)(nit->value);
                double dir[3]={pc->n[0]-pcn->n[0],pc->n[1]-pcn->n[1],pc->n[2]-pcn->n[2]};

                double dis[3]={pc->c[0]-pcn->c[0],pc->c[1]-pcn->c[1],pc->c[2]-pcn->c[2]};
                //printf("pc n:%lf %lf %lf\n",pc->n[0],pc->n[1],pc->n[2]);
                //printf("dis:%lf %lf %lf pc c:%lf %lf %lf\n",dis[0],dis[1],dis[2],pc->c[0],pc->c[1],pc->c[2]);
                
                if(sqrt(dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2])<0.2)
                {
                    if(fabs(dis[0]*pc->n[0]+dis[1]*pc->n[1]+dis[2]*pc->n[2])<0.01)
                    {
                        // printf("shi\n");
                        double num1=(double)node_size(pc->value),num2=(double)node_size(pcn->value);
                        double fac=num1/(num1+num2); 
                        flag=1;
                        pc->n[0]=(fac*pc->n[0]+(1-fac)*pcn->n[0]);
                        pc->n[1]=(fac*pc->n[1]+(1-fac)*pcn->n[1]);
                        pc->n[2]=(fac*pc->n[2]+(1-fac)*pcn->n[2]);
                        double len=sqrt(pc->n[0]*pc->n[0]+pc->n[1]*pc->n[1]+pc->n[2]*pc->n[2]);
                        pc->n[0]/=len;pc->n[1]/=len;pc->n[2]/=len;

                        pc->c[0]=(fac*pc->c[0]+(1-fac)*pcn->c[0]);
                        pc->c[1]=(fac*pc->c[1]+(1-fac)*pcn->c[1]);
                        pc->c[2]=(fac*pc->c[2]+(1-fac)*pcn->c[2]);
                        Node* temp_n=node_splicing(pc->value,pcn->value);
                        free_node(pc->value);
                        pc->value=temp_n;

                        free_node(pcn->value); 
                        free(pcn);

                        break; 
                    }
                    else
                    {
                        // if(fabs(pc->n[2])>0.95&&fabs(pcn->n[2])>0.95)
                        // {
                        //     printf("que: %lf %lf\n",sqrt(dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2]),fabs(dis[0]*pc->n[0]+dis[1]*pc->n[1]+dis[2]*pc->n[2]));  
                        // }
                    }
                } 
            } 
            if(flag==0)
            {
                node_cube_kinds=node_overlying(node_cube_kinds,pcn); 
            }

        } 
        if(jj>70)
        {
         //   break;
        }
        jj++;

    }

    Node*nnit=node_bub_sortn(node_cube_kinds,cmp_node);
    //nnit=(Node*)(nnit->Next);

    //Node* nnit=node_reverse(node_cube_kinds);
    Points_Cluster* pc=(Points_Cluster*)(nnit->value);  
    printf("n:%lf %lf %lf c:%lf %lf %lf\n",pc->n[0],pc->n[1],pc->n[2],pc->c[0],pc->c[1],pc->c[2] );
    n=vw->create_something(vw,points);
    vs=(Viewer_Something*)(n->value);
    vp=(Viewer_Points*)(vs->evolution);

    vp->Data_rows=node_size(pc->value);

    vp->pointsize=5.0;
    vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
    color[0]=0.8;color[1]=0.4;color[2]=0.5;
    i=0;
    for(Node* nit=pc->value;nit!=NULL;nit=(Node*)(nit->Next))
    {
        vp->Data[i*3+0]=((template_v*)(nit->value))->point[0];
        vp->Data[i*3+1]=((template_v*)(nit->value))->point[1];
        vp->Data[i*3+2]=((template_v*)(nit->value))->point[2];
        i++;
    } 
    printf("i:%d\n",vp->Data_rows );
    vp->set_color(vp,color);
    free_node(node_reverse(n));

    auto *ti=(Temp_intera*)malloc(sizeof(Temp_intera));
    ti->vs=vs;

    
    ti->value=nnit;
    ti->voi=voi;
    char intera[]="Intera";
    n=vw->create_something(vw,intera);
    vs=(Viewer_Something*)(n->value);
    auto vi=(Viewer_Intera*)(vs->evolution);

    vi->representation=ti;
    vi->key_callback=temp_intera_key_callback;
    
    free_node(node_reverse(n));

    printf("end3\n");
    Node* temp_n=NULL;
    for(auto vit=mesh.v_begin(&mesh);vit!=mesh.v_end(&mesh);vit++)
    {
        template_v* v=(template_v*)(quote(vit));
        float dir[3]={v->point[0]-pc->c[0],v->point[1]-pc->c[1],v->point[2]-pc->c[2]};

        if(fabs(dir[0]*pc->n[0]+dir[1]*pc->n[1]+dir[2]*pc->n[2])<0.02)
        {
            temp_n=node_overlying(temp_n,v);
        } 
    }
    for(Node* nit=temp_n;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_v* v=(template_v*)(nit->value);
        mesh.delete_vertex(&mesh,*v,false);
    }
   
   // printf("end1:%d\n",mesh.dimension);
    mesh.dimension=0;
    _WriteCell_(&mesh,"tree1.cell");

    printf("end2\n");
    Mesh_free(&mesh); 
    
    // char faces[]="Faces";
    // n=vw->create_something(vw,faces);
    // vs=(Viewer_Something*)(n->value);
    // auto vf=(Viewer_Faces*)(vs->evolution);
    // vf->Data_rows=4;
    // vf->Data_index_rows=2;
    // vf->Data=(float*)malloc(sizeof(float)*3*vf->Data_rows);
    // vf->Data_index=(unsigned int*)malloc(sizeof(unsigned int)*4*vf->Data_index_rows);
    // float cube_i[4]={-1,1,1,-1},cube_j[4]={-1,-1,1,1};
    // for(int i=0;i<4;i++)
    // {
    //     vf->Data[i*3+0]=cube_i[i];vf->Data[i*3+1]=cube_j[i];vf->Data[i*3+2]=((pc->c[0]-vf->Data[i*3+0])*pc->n[0]+(pc->c[1]-vf->Data[i*3+1])*pc->n[1])/pc->n[2]+pc->c[2];
    // } 
    // vf->Data_index[0]=3;vf->Data_index[1]=0;vf->Data_index[2]=1;vf->Data_index[3]=3;
    // vf->Data_index[4]=3;vf->Data_index[5]=1;vf->Data_index[6]=2;vf->Data_index[7]=3;
    


    // free_node(node_reverse(n)); 


}
void test_matrix()
{
    MatrixXf A;
    A.resize(4,3);
    A.setZero();

    A(0,0)=1;A(0,1)=1;A(0,2)=1;
    A(1,0)=1;A(1,1)=2;A(1,2)=3;
    A(2,0)=1;A(2,1)=10;A(2,2)=100;
    A(3,0)=1;A(3,1)=0;A(3,2)=0;
      
    JacobiSVD<Eigen::MatrixXf> svd(A,ComputeThinU | ComputeThinV);
    MatrixXf V=svd.matrixV();


    MatrixXf S=svd.singularValues();

    std::cout<<"V :\n"<<V<<std::endl;
    std::cout<<"S :\n"<<S<<std::endl; 
    srand((unsigned)time(NULL));
    float data[100][3]={0};
    
    float centroid[3]={0};
    for(int i=0;i<100;i++)
    {
        data[i][0]=(rand()%800)/100.0-4;
        data[i][1]=(rand()%800)/100.0-4;
        data[i][2]=(rand()%200)/100.0-1;
        centroid[0]+=data[i][0];centroid[1]+=data[i][1];centroid[2]+=data[i][2];
        printf("%lf %lf %lf\n",data[i][0],data[i][1],data[i][2]);
    }   
    centroid[0]/=100.0;centroid[1]/=100.0;centroid[2]/=100.0;

    printf("centroid:%lf %lf %lf\n",centroid[0],centroid[1],centroid[2] );
    for(int i=0;i<100;i++)
    {
        data[i][0]-=centroid[0];
        data[i][1]-=centroid[1];
        data[i][2]-=centroid[2];
    }
    A.resize(100,3);
    A.setZero();
    for(int i=0;i<100;i++)
    {
        A(i,0)=data[i][0];
        A(i,1)=data[i][1];
        A(i,2)=data[i][2];
    } 
    JacobiSVD<Eigen::MatrixXf> svd1(A,ComputeThinU | ComputeThinV);
    MatrixXf V1=svd1.matrixV();


    MatrixXf S1=svd1.singularValues();
    std::cout<<V1<<std::endl; 

}
// void test_io(const char* filename)
// {
// #ifdef WIN32
//     FILE *infile,*outfile;
//     fopen_s(&infile,filename,"r");
//     fopen_s(&outfile,"testio.off","w");

// #else
//     FILE *infile=fopen(filename,"r");
//     FILE *outfile=fopen("testio.off","w");
// #endif
//     if(!infile)
//     {
//         printf("cant't open this file\r\n");
//         return;
//     }
//     if(!outfile)
//     {
//         printf("catn open this file\n" );
//         return ;
//     }
//     char off[120]={0};
//     fscanf(infile,"%s",off);
//     fprintf(outfile, "%s\n",off );
//     fscanf(infile,"%s",off);
//     fprintf(outfile, "%s ",off );
//     fscanf(infile,"%s",off);
//     fprintf(outfile, "%s ",off );
//     fscanf(infile,"%s",off);
//     fprintf(outfile, "%s\n",off );
//     int i=0;
//     while(fscanf(infile,"%s",off)==1)
//     {
//        // printf("%s", off); 
//         if(i%4!=3)
//         {

//             fprintf(outfile,"%s ",off);
//         }
//         else
//         {
//             fprintf(outfile, "\n");
//         }
//         i++;

//     }


    
//    // fscanf(infile,"%s",off);
//    // fprintf(outfile,"background_dim= %d\n",back_ground);
// }
int main(int argc,char**argv)
{
//objtooff("qinbei.obj");
  
    //KD_Node* kn= create_kd_tree_from_mesh(&mesh);

   /* points_cloud_analyze_points(kn,&pca);
    printf("%lf %lf\n",pca.xs[0],pca.xs[1] );
    printf("%lf %lf\n",pca.ys[0],pca.ys[1] );
    printf("%lf %lf\n",pca.zs[0],pca.zs[1] );
*/
    //****************
    // test_matrix();
//    test_io("tree3.off");
    Viewer_World_Manager*vwm=(Viewer_World_Manager*)malloc(sizeof(Viewer_World_Manager));
    viewer_world_manager_init(vwm);
    

    Viewer_World* vw=vwm->create_world(vwm,NULL);
    //viewer_world_init(&vw);

    Viewer_Opengl_Interpreter *voi=(Viewer_Opengl_Interpreter*)malloc(sizeof(Viewer_Opengl_Interpreter));
    

    viewer_opengl_interpreter_initn(voi,vwm);
    test_division_earth(vw,voi);

    //voi.world=&vw;
    //test_construct_mesh(&vw); 


    //**************************
    /*
    n=vw.create_something(&vw,points);
    vs=(Viewer_Something*)(n->value);
    vp=(Viewer_Points*)(vs->evolution);
    vp->Data_rows=node_size((Node*)(nit->value));
    printf("node_size:%d\n",vp->Data_rows );
    vp->pointsize=7.0;
    vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
    i=0;
    for(Node* nnit=(Node*)(nit->value);nnit!=NULL;nnit=(Node*)(nnit->Next))
    {
        template_v* v=(template_v*)(nnit->value);
        vp->Data[i]=v->point[0];
        i++;
        vp->Data[i]=v->point[1];
        i++;
        vp->Data[i]=v->point[2];
        i++;
    }
    color[0]=0.1;color[1]=0.8;color[2]=0.2;
    
    vp->set_color(vp,color);*/
    /*
    char edges[]="Edges";
    Node* n=vw.create_something(&vw,edges);
    auto vs=(Viewer_Something*)(n->value);
    auto ve=(Viewer_Edges*)(vs->evolution);
    ve->Data_rows=8;
    ve->Data_index_rows=12;
    ve->color_rows=ve->Data_index_rows;
    ve->Data=(float*)malloc(sizeof(float)*3*ve->Data_rows); 
    ve->Data_index=(unsigned int*)malloc(sizeof(unsigned int)*2*ve->Data_index_rows);

    int l=0;
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            for(int k=0;k<2;k++)
            {

                ve->Data[l*3+0]=pca->xs[i];
                ve->Data[l*3+1]=pca->ys[j];
                ve->Data[l*3+2]=pca->zs[k];
                l++;
            }
        }
    }
    ve->Data_index[0]=0;ve->Data_index[1]=1;
    ve->Data_index[2]=2;ve->Data_index[3]=3;
    ve->Data_index[4]=0;ve->Data_index[5]=2;
    ve->Data_index[6]=1;ve->Data_index[7]=3; 

    ve->Data_index[8]=4;ve->Data_index[9]=5;
    ve->Data_index[10]=6;ve->Data_index[11]=7;
    ve->Data_index[12]=4;ve->Data_index[13]=6;
    ve->Data_index[14]=5;ve->Data_index[15]=7;

    ve->Data_index[16]=0;ve->Data_index[17]=4;
    ve->Data_index[18]=1;ve->Data_index[19]=5;   
    ve->Data_index[20]=2;ve->Data_index[21]=6;
    ve->Data_index[22]=3;ve->Data_index[23]=7;
    free_node(node_reverse(n));
*/
/*
    char points[]="Points";
    n=vw.create_something(&vw,points);
    vs=(Viewer_Something*)(n->value);
    auto vp=(Viewer_Points*)(vs->evolution);
    OC_Node* ocn=pca.tree;
    Node* node=NULL;
    for(auto oit=octree_begin(ocn);oit!=octree_end(ocn);oit++)
    {
        if(node_size(oit.it->value)>10)
        {
            node=oit.it->value;
            break;
        }
    }
    vp->Data_rows=node_size(node);
    vp->pointsize=6.0;
    vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
    int i=0;
    for(Node* nit=node;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_v* vv=(template_v*)(nit->value);
        vp->Data[i]=vv->point[0];
        i++;
        vp->Data[i]=vv->point[1];
        i++;
        vp->Data[i]=vv->point[2];
        i++;
    } 
    float color[4]={0.9,0.3,0.8,1.0};

    vp->set_color(vp,color); 
    free_node(node_reverse(n)); 
    */
   // vp->color_rows=vp->Data_rows;
     
    //printf("kn node size:%d\n",kd_node_size(kn) );
   // vw.print_self(&vw);
    set_default_voi(voi,vw);

    printf("endfdsdsdddddddddddddddd\n");
    voi->interpreter(voi);
    viewer_opengl_interpreter_free(voi);
    return 0;
}
